package com.spring.boot.demo.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author ZhuYouBin
 * @version 1.0.0
 * @Date: 2022/11/5 15:45
 * @Description
 */
@RestController
@RequestMapping("/api/jedis")
public class RedisDemo {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @GetMapping("/zset")
    public String opsForZSet() {
        // 操作 ZSet 有序集合
        ZSetOperations<String, Object> ops = redisTemplate.opsForZSet();
        // 添加元素
        ops.add("zs1", "v100", 1);
        // 添加多个元素
        Set<ZSetOperations.TypedTuple<Object>> set = new HashSet<>();
        for (int i = 0; i < 9; i++) {
            set.add(new DefaultTypedTuple<>("v100" + i, (i + 10.0)));
        }
        ops.add("zs2", set);
        // 删除多个指定值的元素，返回删除成功的个数
        Long count = ops.remove("zs2", "v100");
        // 统计指定score范围里面的所有元素个数
        Long zs1 = ops.count("zs1", 1.0, 100.0);
        // 返回有序集合zset中，指定value值的排序等级
        Long rank = ops.rank("zs1", "v200");
        // 返回zset集合中指定区间的元素
        Set<Object> zs11 = ops.range("zs2", 1, 3);
        System.out.println(zs11);
        // 将指定值的score分数加上delta数值
        Double score = ops.incrementScore("zs", "v100", 100);
        // 获取score分数在指定区间的所有元素
        Set<Object> zs2 = ops.rangeByScore("zs2", 20, 50);
        // 获取指定值的score分数
        Double score1 = ops.score("zs1", "v100");
        return "success.";
    }

    @GetMapping("/hash")
    public String opsForHash() {
        // 操作 hash 表
        HashOperations<String, Object, Object> ops = redisTemplate.opsForHash();
        // 添加单个元素
        ops.put("h1", "f1", "v100");
        ops.put("h1", "f11", 100);
        // 添加多个元素
        Map<String, String> map = new HashMap<>();
        map.put("f2", "v200");
        map.put("f3", "v300");
        ops.putAll("h1", map);
        // 当对应的hashKey不存在时候，才能够添加成功
        Boolean suc = ops.putIfAbsent("h1", "f1", "v1100");
        // 获取hash表指定key的元素
        Object val = ops.get("h1", "f1");
        // 删除hash表中多个key，返回删除成功的个数
        Long count = ops.delete("h1", "f3", "f4");
        // 获取所有的hashKey
        Set<Object> h1 = ops.keys("h1");
        // 获取所有的hashVal
        List<Object> vals = ops.values("h1");
        // 获取hash表中的key-value值
        Map<Object, Object> h11 = ops.entries("h1");
        // 判断hash表中是否存在某个hashKey
        Boolean hasKey = ops.hasKey("h1", "f1");
        // 将key中某个hashKey的值加上指定数值
        Long ans = ops.increment("h1", "f11", 10);
        // 返回hashKey的value值长度
        Long len = ops.lengthOfValue("h1", "f1");
        return "success.";
    }

    @GetMapping("/set")
    public String opsForSet() {
        // 操作set无序集合
        SetOperations<String, Object> ops = redisTemplate.opsForSet();
        // 添加单个、多个元素, 返回添加成功的个数
        Long add = ops.add("z1", "v100", "v200", "v200");
        // 删除指定元素，返回删除成功的个数
        Long count = ops.remove("z1", "v1100", "v100");
        // 判断某个元素是否存在集合里面
        Boolean member = ops.isMember("z1", "v2200");
        // 删除单个或指定数量的元素
        List<Object> z1 = ops.pop("z1", 2);
        // 获取所有set集合元素
        Set<Object> z11 = ops.members("z1");
        // 随机获取一个元素
        Object z12 = ops.randomMember("z1");
        // 随机获取指定数量的元素
        List<Object> z13 = ops.randomMembers("z1", 3);
        // 将key1集合中的元素移动到key2集合里面
        Boolean move = ops.move("z1", "v200", "z2");
        // 求多个key中的差集元素，即：公共元素。
        Set<Object> intersect = ops.intersect("z1", "z2");
        // 求多个key中的并集元素，即：所有元素。
        Set<Object> union = ops.union("z1", "z2");
        // 求第一个key中在其他key中都不存在的元素集合，即：key1特有元素
        Set<Object> difference = ops.difference("z1", "z2");
        return "success.";
    }

    @GetMapping("/list")
    public String opsForList() {
        // 操作List集合
        ListOperations<String, Object> ops = redisTemplate.opsForList();
        // 列表左边添加单个元素
        ops.leftPush("lk1", "v100");
        // 列表左边添加多个元素
        ops.leftPushAll("lk2", "v100", "v200");
        // 列表右边添加元素：rightPush、rightPushAll
        // 列表左侧删除元素
        Object lk1 = ops.leftPop("lk1");
        // 列表右侧删除元素
        Object lk2 = ops.rightPop("lk2");
        // 从列表中删除指定value的元素count个，返回删除成功的个数
        Long count = ops.remove("lk2", 2, "v200");
        // 获取指定下标的元素
        Object lk11 = ops.index("lk1", 0);
        // 获取列表中指定下标范围的所有元素
        List<Object> lk21 = ops.range("lk2", 0, -1);
        // 将列表1中右侧元素删除，添加到列表2中的左侧，返回列表1中删除的元素
        Object push = ops.rightPopAndLeftPush("lk1", "lk2");
        return "success.";
    }

    @GetMapping("/string")
    public String opsForValue() {
        // 操作字符串类型
        ValueOperations<String, Object> ops = redisTemplate.opsForValue();
        // 添加单个数据
        ops.set("k1", "v100");
        ops.set("k2", "v200", 10, TimeUnit.SECONDS); // 过期时间
        // key 不存在，才能够添加成功
        Boolean flag = ops.setIfAbsent("k2", "v300");
        // key 存在时候，才能够添加成功
        flag = ops.setIfPresent("k99", "v999");
        // 添加多个数据
        Map<String, String> map = new HashMap<>();
        map.put("k3", "v300");
        map.put("k4", "v400123456789");
        ops.multiSet(map);
        // 所有的key不存在，才能够添加成功
        Boolean ans = ops.multiSetIfAbsent(map);
        // 返回 key 对应的 value 字符串长度
        Long len = ops.size("k4");
        // 获取指定 key 的 value
        Object val = ops.get("k3");
        // 获取指定 key 的 value 值指定范围[start,end]的内容
        val = ops.get("k4", 2, 5);
        // 替换指定 key 的value 值，并且返回替换前的value值
        val = ops.getAndSet("k4", "csdn");
        // 追加指定 key 的 value 值，返回追加后的字符串长度
        Integer len2 = ops.append("k4", "-hello world");
        ops.set("vv100", 100);
        // 将 key 的 value 值加1，或者指定值
        ops.increment("vv100");
        ops.increment("vv100", 20);
        // 将 key 的 value 值减1，或者指定值
        ops.decrement("vv100");
        ops.decrement("vv100", 40);
        return "success.";
    }

}
